<?php

/**
 * 应用程序的公共控制器基础类
 *
 * 可以在这个类中添加方法来完成应用程序控制器共享的功能。
 */
abstract class Controller_Abstract extends QController_Abstract
{
    /**
     * 控制器动作要渲染的数据
     *
     * @var array
     */
    protected $_view = array();

    /**
     * 控制器要使用的视图类
     *
     * @var string
     */
    protected $_view_class = 'QView_Render_PHP';

    /**
     * 控制器要使用的视图
     *
     * @var string
     */
    protected $_viewname = null;

    /**
     * 控制器所属的应用程序
     *
     * @var CommunityApp
     */
    protected $_app;

    /**
     * 构造函数
     */
    function __construct($app)
    {
        parent::__construct();
        $this->_app = $app;
    }

    /**
     * 执行指定的动作
     *
     * @return mixed
     */
    function execute($action_name, array $args = array())
    {
        $action_method = "action{$action_name}";

        // 执行指定的动作方法
        $this->_before_execute();

        #IFDEF DBEUG
        QLog::log('EXECUTE ACTION: '. get_class($this) . '::' . $action_method . '()', QLog::DEBUG);
        #ENDIF

        $response = call_user_func_array(array($this, $action_method), $args);
        $this->_after_execute($response);

        if (is_null($response) && is_array($this->_view))
        {
            // 如果动作没有返回值，并且 $this->view 不为 null，
            // 则假定动作要通过 $this->view 输出数据
            $config = array('view_dir' => $this->_getViewDir());
            $response = new $this->_view_class($config);
            $response->setViewname($this->_getViewName())->assign($this->_view);
            $this->_before_render($response);
        }
        elseif ($response instanceof $this->_view_class)
        {
            $response->assign($this->_view);
            $this->_before_render($response);
        }

        return $response;
    }

    /**
     * 指定的控制器动作未定义时调用
     *
     * @param string $action_name
     */
    function _on_action_not_defined($action_name)
    {
    }

    /**
     * 执行控制器动作之前调用
     */
    protected function _before_execute()
    {
    	require Q::ini('custom_system/lib_dir') . 'log.php';
    	if (isset($_POST[Q::ini('unique_token_name')]))
    	{
    		session_start();
    		if (isset($_SESSION[Q::ini('unique_token_name')][$_POST[Q::ini('unique_token_name')]]))
    		{
    			unset($_SESSION[Q::ini('unique_token_name')][$_POST[Q::ini('unique_token_name')]]);
    			unset($_POST[Q::ini('unique_token_name')]);
    		}
    		else
    		{
    			include 'repeat_post.php';exit;
    		}
    		session_write_close();
    	}
    	if (Q::ini('unique_token_open'))
    	{
			if (isset($_GET[Q::ini('unique_token_name')]))
	    	{
	    		session_start();
	    		if (isset($_SESSION[Q::ini('unique_token_name')][$_GET[Q::ini('unique_token_name')]]))
	    		{
	    			unset($_SESSION[Q::ini('unique_token_name')][$_GET[Q::ini('unique_token_name')]]);
	    			unset($_GET[Q::ini('unique_token_name')]);
	    		}
	    		else
	    		{
	    			include 'repeat_post.php';exit;
	    		}
	    		session_write_close();
	    	}
    	}
    	$cache = new QCache_File();
    	// $svn_version = $cache->get(Q::ini('app_config/APPID') . '_svn_version');
    	// if ( ! $svn_version)
    	// {
    	// 	$server = php_uname();
    	// 	if (preg_match('(windows|Windows)', $server))
    	// 	{
    	// 		$svn_version = 0;
    	// 	}
    	// 	else
    	// 	{
	    // 		$svn_info = @shell_exec("svn info " . Q::ini('app_config/ROOT_DIR'));
	    // 		$svn_info = explode("\n", $svn_info);
	    // 		$version = explode(":", $svn_info[4]);
	    // 		$svn_version = trim($version[1]);
    	// 	}
    	// 	$cache->set(Q::ini('app_config/APPID').'_svn_version', $svn_version);
    	// }
    	// $this->_view['svn_version'] = $svn_version;
    	if (CURRENT_USER_ID)
    	{
    		$all_nca = $cache->get(Q::ini('app_config/APPID').'_all_nca');
    		if ( ! $all_nca)
    		{
    			$display_flag = Q::ini('custom_flag/permissions_actions_display_flag/show/value');
    			$all_nca = array();
    			$namespace = Permissions_Actions::find('controller=? and action=? and display_flag=?', '', '', $display_flag)->order('sort asc')->asArray()->getAll();
    			foreach ($namespace as $n)
    			{
    				$controller = Permissions_Actions::find('namespace=? and controller!=? and action=? and display_flag=?', $n['namespace'], '', '', $display_flag)->order('sort asc')->asArray()->getAll();
    				foreach ($controller as $c)
    				{
    					$action = Permissions_Actions::find('namespace=? and controller=? and action!=? and display_flag=?', $c['namespace'], $c['controller'], '', $display_flag)->order('sort asc')->asArray()->getAll();
    					foreach ($action as $a)
    					{
	    					$all_nca[$a['id']] = array(
	    						'id' => $c['id'],
	    						'namespace' => $n['namespace'],
	    						'namespace_name' => $n['name'],
	    						'controller' => $c['controller'],
	    						'controller_name' => $c['name'],
	    						'action' => $a['action'],
	    						'action_name' => $a['name'],
	    						'param' => $a['param']
	    					);
    					}
    				}
    			}
    			$cache->set(Q::ini('app_config/APPID').'_all_nca', $all_nca);
    		}
    		$ids = array();
    		$mapping = Roles_Actions_Mapping::find('roles_users_mapping.user_id=?', CURRENT_USER_ID)
	    		->joinLeft('roles_users_mapping', '', 'roles_users_mapping.roles_id=roles_actions_mapping.roles_id')
	    		->asArray()->getAll();
    		foreach ($mapping as $m)
    		{
    			$ids[$m['permissions_actions_id']] = $m['permissions_actions_id'];
    		}
    		$this_user_actions = array_intersect_key($all_nca, $ids);
    		$this_user_nca = array();
    		foreach ($this_user_actions as $tua)
    		{
    			if ( ! isset($this_user_nca[$tua['namespace']]['first_action_url']))
    			{
    				$this_user_nca[$tua['namespace']]['first_action_url'] = url($tua['namespace'] . '::' . $tua['controller'] . '/' . $tua['action']);
    			}
    			$this_user_nca[$tua['namespace']]['name'] = $tua['namespace_name'];
	    		$this_user_nca[$tua['namespace']]['children'][$tua['controller']]['name'] = $tua['controller_name'];
	    		$this_user_nca[$tua['namespace']]['children'][$tua['controller']]['children'][$tua['action']]['name'] = $tua['action_name'];
	    		$this_user_nca[$tua['namespace']]['children'][$tua['controller']]['children'][$tua['action']]['param'] = $tua['param'];
    		}
    		$this->_view[Q::ini('app_config/APPID') . '_nca'] = $this_user_nca;
    		$current_namespace = Permissions_Actions::find('namespace=? and controller=? and action=?', isset($_GET['namespace']) ? $_GET['namespace'] : 'default', '', '')->asArray()->getOne();
    		$current_controller = Permissions_Actions::find('namespace=? and controller=? and action=?', isset($_GET['namespace']) ? $_GET['namespace'] : 'default', isset($_GET['controller']) ? $_GET['controller'] : 'default', '')->asArray()->getOne();
    		$current_action = Permissions_Actions::find('namespace=? and controller=? and action=?', isset($_GET['namespace']) ? $_GET['namespace'] : 'default', isset($_GET['controller']) ? $_GET['controller'] : 'default', isset($_GET['action']) ? $_GET['action'] : 'index')->asArray()->getOne();
    		$this->_view[Q::ini('app_config/APPID') . '_current_nca'] = array(
    			'namespace' => $current_namespace['name'],
    			'controller' => $current_controller['name'],
    			'action' => $current_action['name']
    		);
    	}
    }

    /**
     * 执行控制器动作之后调用
     *
     * @param mixed $response
     */
    protected function _after_execute(& $response)
    {
    }

    /**
     * 渲染之前调用
     *
     * @param QView_Render_PHP
     */
    protected function _before_render($response)
    {
    }

    /**
     * 准备视图目录
     *
     * @return array
     */
    protected function _getViewDir()
    {
        if ($this->_context->module_name)
        {
            $dir = Q::ini('app_config/MODULE_DIR') . "/{$this->_context->module_name}/view";
        }
        else
        {
            $dir = Q::ini('app_config/APP_DIR') . '/view';
        }

        if ($this->_context->namespace)
        {
            $dir .= "/{$this->_context->namespace}";
        }
        return $dir;
    }

    /**
     * 确定要使用的视图
     *
     * @return string
     */
    protected function _getViewName()
    {
        if ($this->_viewname === false)
        {
            return false;
        }
        $viewname = empty($this->_viewname) ? $this->_context->action_name : $this->_viewname;
        return strtolower("{$this->_context->controller_name}/{$viewname}");
    }

    /**
     * 显示一个提示页面，然后重定向浏览器到新地址
     *
     * @param string $caption
     * @param string $message
     * @param string $url
     * @param string $ack //add by zen
     * @param int $delay
     * @param string $script
     *
     * @return QView_Render_PHP
     */
    protected function _redirectMessage($caption, $message, $url, $ack='', $delay = '', $script = '')
    {
    	$delay = Q::ini('custom_system/redirect_time');
        $config = array('view_dir' => Q::ini('custom_system/view_dir'));
        $response = new $this->_view_class($config);
        $response->setViewname('redirect_message');
        $response->assign(array(
            'message_caption'   => $caption,
            'message_body'      => $message,
            'redirect_url'      => $url,
        	'ack'				=> $ack,
            'redirect_delay'    => $delay,
            'hidden_script'     => $script
        ));
        return $response;
    }
}

